React 团队面向开发者给出了两条 React-Hooks 的使用原则,原则的内容如下:
- 只在 React 函数中调用
Hook; - 不要在循环、条件或嵌套函数中调用
Hook。
从现象看问题:若不保证 Hooks 执行顺序,会带来什么麻烦
先来看一个小 Demo:
import React, { useState } from "react";
function PersonalInfoComponent() {
// 集中定义变量
let name, age, career, setName, setCareer;
// 获取姓名状态
[name, setName] = useState("修言");
// 获取年龄状态
[age] = useState("99");
// 获取职业状态
[career, setCareer] = useState("我是一个前端,爱吃小熊饼干");
// 输出职业信息
console.log("career", career);
// 编写 UI 逻辑
return (
<div className="personalInfo">
<p>姓名:{name}</p>
<p>年龄:{age}</p>
<p>职业:{career}</p>
<button
onClick={() => {
setName("秀妍");
}}
>
修改姓名
</button>
</div>
);
}
export default PersonalInfoComponent;
@前端进阶之旅: 代码已经复制到剪贴板
这个 PersonalInfoComponent 组件渲染出来的界面长这样:

PersonalInfoComponent 用于对个人信息进行展示,这里展示的内容包括姓名、年龄、职业。出于测试效果需要,PersonalInfoComponent 还允许你点击“修改姓名”按钮修改姓名信息。点击一次后,“修言”会被修改为“秀妍”,如下图所示:

到目前为止,组件的行为都是符合我们的预期的,一切看上去都是那么的和谐。但倘若我对代码做一丝小小的改变,把一部分的 useState 操作放进 if 语句里,事情就会变得大不一样。改动后的代码如下:
import React, { useState } from "react";
// isMounted 用于记录是否已挂载(是否是首次渲染)
let isMounted = false;
function PersonalInfoComponent() {
// 定义变量的逻辑不变
let name, age, career, setName, setCareer;
// 这里追加对 isMounted 的输出,这是一个 debug 性质的操作
console.log("isMounted is", isMounted);
// 这里追加 if 逻辑:只有在首次渲染(组件还未挂载)时,才获取 name、age 两个状态
if (!isMounted) {
// eslint-disable-next-lin